package com.ht.api.db.request;

import java.util.List;

import javax.sql.DataSource;

import com.ht.api.db.Db;
import com.ht.api.db.DbConfig;
import com.ht.api.db.DbList;
import com.ht.api.db.DbPage;
import com.ht.api.db.Entity;
import com.ht.api.db.SqlParser;
import com.ht.api.db.StreamLoadConfig;
import com.ht.api.db.annotate.FuncAdd;
import com.ht.api.db.annotate.FuncBatch;
import com.ht.api.db.annotate.FuncCall;
import com.ht.api.db.annotate.FuncDel;
import com.ht.api.db.annotate.FuncEdit;
import com.ht.api.db.annotate.FuncParams;
import com.ht.api.db.annotate.FuncQuery;
import com.ht.api.db.bean.DataResult;
import com.ht.api.db.bean.SessionBean;
import com.ht.api.db.exception.HtException;
import com.ht.api.db.util.FunctionUtil;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

/**
 * 请求处理接口的工具类
 * @author asq
 * @createTime 2025年4月15日 15:19:54
 */
public class HandleRequestUtil {
	/** 前端参数变量名 */
	public static final String PARAM = "param";
	
	/**
	 * 执行一个Func
	 * @param me 
	 * @param key 接口key
	 * @return
	 */
	public static DataResult callFunc(SessionBean me, String key) {
		// 根据key，获取具体接口
		IHandleRequest function = FunctionUtil.getFunction(key);
		if (function == null) {
			throw new HtException("找不到HandleRequest函数：" + key);
		}
		
		// 获取接口的参数配置
		FuncParams funcParams = function.getClass().getAnnotation(FuncParams.class);
		JSONObject param = HandleRequestHelper.getFuncParam(funcParams);
		
		return callFunc(me, function, param);
	}
	
	/**
	 * 执行一个Func
	 * @param me 
	 * @param key 接口key
	 * @param param 参数
	 * @return
	 */
	public static DataResult callFunc(SessionBean me, String key, JSONObject param) {
		// 根据key，获取具体接口
		IHandleRequest function = FunctionUtil.getFunction(key);
		if (function == null) {
			throw new HtException("找不到HandleRequest函数：" + key);
		}
		
		return callFunc(me, function, param);
	}
	
	/**
	 * 执行一个Func
	 * @param me 
	 * @param function 要执行的Func
	 * @param param 参数
	 * @return
	 */
	private static DataResult callFunc(SessionBean me, IHandleRequest function, JSONObject param) {
		Class<?> implClass = function.getClass();
        FuncAdd funcAdd = implClass.getAnnotation(FuncAdd.class);
        FuncEdit funcEdit = implClass.getAnnotation(FuncEdit.class);
        FuncDel funcDel = implClass.getAnnotation(FuncDel.class);
        FuncQuery funcQuery = implClass.getAnnotation(FuncQuery.class);
        FuncBatch funcBatch = implClass.getAnnotation(FuncBatch.class);
        FuncCall funcCall = implClass.getAnnotation(FuncCall.class);
        
        // 处理del时，前端可能会传数组的情况
        JSONObject myParam = null;
        Object paramObj = param.get(PARAM);
		if (paramObj instanceof JSONArray) {
			myParam = JSONUtil.createObj().set("batch", paramObj);
		} else {
			myParam = param.getJSONObject(PARAM);
		}
		
		// 构造一个容器，用来存放各种数据
		DataResult result = DataResult.create();

        // 执行前置函数
        function.before(me, myParam, result);
        
        // 执行本身
        if (funcAdd != null) {
        	add(me, funcAdd.value(), param, result);
        } else if (funcEdit != null) {
        	edit(me, funcEdit.value(), param, result);
        } else if (funcDel != null) {
        	del(me, funcDel.value(), param, result);
        } else if (funcQuery != null) {
        	query(me, funcQuery.value(), param, result);
        } else if (funcBatch != null) {
        	batch(me, funcBatch.value(), param, result);
        } else if (funcCall != null) {
        	function.execute(me, myParam, result);
        }
        
        // 执行后置函数
    	function.after(me, myParam, result);
        
        return result;
	}
	
	private static void add(SessionBean me, String table, JSONObject param, DataResult result) {
    	DataSource ds = me.isSysCommonCall() ? DbConfig.useSysDb() : me.getDataSource();
		Entity entity = param.getBean(PARAM, Entity.class).setTable(table).set("sys_creator", me.getLoginIdStr());
		Db.insert(ds, entity);
		result.set("main_id", entity.getStr("main_id"));
	}
	
	private static void edit(SessionBean me, String table, JSONObject param, DataResult result) {
    	DataSource ds = me.isSysCommonCall() ? DbConfig.useSysDb() : me.getDataSource();
		Entity entity = param.getBean(PARAM, Entity.class).setTable(table);
		if (!entity.containsKey("main_id")) {
			throw new HtException("没有主键main_id，无法执行修改~");
		}
		Db.insert(ds, entity);
	}
	
	private static void del(SessionBean me, String table, JSONObject param, DataResult result) {
    	DataSource ds = me.isSysCommonCall() ? DbConfig.useSysDb() : me.getDataSource();
		Object paramObj = param.get(PARAM);
		if (paramObj instanceof JSONArray) {
			// 根据main_id数组进行批量删除
			List<Entity> list = JSONUtil.toList((JSONArray)paramObj, Entity.class);
			list.stream().forEach(b -> {
				if (!b.containsKey("main_id")) {
					throw new HtException("删除操作必须提供main_id字段~");
				}
				b.setTable(table).set("sys_deleted", 0).set("table", table);
			});
			Db.insertBatch(ds, list, false);
		} else {
			Entity entity = param.getBean(PARAM, Entity.class);
			if (entity.containsKey("where")) {
				// 按条件批量删除
				SqlParser sql = param.getBean(PARAM, SqlParser.class).setTable(table);
				DbList dbList = sql.query(ds);
				dbList.stream().forEach(b -> {
					b.setTable(table).set("sys_deleted", 0).set("table", table);
				});
				Db.insertBatch(ds, dbList, false);
			} else {
				// 按main_id删除
				entity.setTable(table).set("sys_deleted", 0).set("table", table);
				if (!entity.containsKey("main_id")) {
					throw new HtException("删除操作必须提供main_id字段~");
				}
				Db.insert(ds, entity);
			}
		}
	}
	
	private static void batch(SessionBean me, String table, JSONObject param, DataResult result) {
		StreamLoadConfig slc = me.isSysCommonCall() ? DbConfig.useSysSLC() : me.getStreamLoadConfig();
		Object paramObj = param.get(PARAM);
		if (paramObj instanceof JSONArray) {
			List<Entity> list = JSONUtil.toList((JSONArray)paramObj, Entity.class);
			list.stream().forEach(b -> b.setTable(table).set("sys_creator", me.getLoginIdStr()));
			Db.insertBatchWithStream(slc, list);
		} else {
			throw new HtException(String.format("%s字段必须为JSONArray数组~", PARAM));
		}
	}
	
	private static void query(SessionBean me, String table, JSONObject param, DataResult result) {
    	DataSource ds = me.isSysCommonCall() ? DbConfig.useSysDb() : me.getDataSource();
		SqlParser sql = param.getBean(PARAM, SqlParser.class).setTable(table);
		
		// 添加默认排序
		if (!sql.containsKey(SqlParser.ORDER)) {
			if ("db_table".equals(table) || "db_column".equals(table)) {
				sql.order("order_num", "desc").order("sys_time", "asc").order("main_id", "asc");
				
				// 排除db_table的元数据
				String field = "db_table".equals(table) ? "code" : "table_code";
				sql.where(field, "!=", "db_table");
				sql.where(field, "!=", "db_column");
			} else {
				sql.order("sys_creator", "desc").order("sys_time", "desc").order("main_id", "desc");
			}
		}
		
		result.set(DbPage.create(ds, sql));
	}
}
